package com.example.lxj.base.utils;

import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.example.lxj.base.config.JWTConfig;
import com.example.lxj.system.entity.SysUser;
import com.example.lxj.system.entity.SysUserToken;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
@Component
public class JWTUtils {

    private static JWTConfig jwtConfig;

    @Autowired
    public JWTUtils(JWTConfig jwtConfig) {
        JWTUtils.jwtConfig = jwtConfig;
    }

    /**
     * 创建TOKEN
     * @param sysUser
     * @return
     */
    public static SysUserToken createToken(SysUser sysUser){
        // 设置装载信息
        HashMap<String,Object> payload = new HashMap<>();
        payload.put("id", sysUser.getUserId());
//        payload.put("userName", sysUser.getUserName());
        Instant nowInstant = Instant.now();
        Instant expireTime = nowInstant.plus(jwtConfig.getExpireTime(), ChronoUnit.MINUTES);
        String token =  JWT.create()
                .withPayload(payload)
                .withSubject(sysUser.getUserId().toString())
                .withExpiresAt(expireTime)
                .sign(Algorithm.HMAC512(jwtConfig.secret));
        SysUserToken sysUserToken = new SysUserToken();
        sysUserToken.setUserId(sysUser.getUserId());
        sysUserToken.setUserToken(token);
        sysUserToken.setCreateTime(DateUtil.date(nowInstant));
        sysUserToken.setExpireTime(DateUtil.date(expireTime));
        return sysUserToken;
    }


    /**
     * 验证token
     * @param token
     */
    public static String validateToken(String token){
        try {
            return JWT.require(Algorithm.HMAC512(jwtConfig.secret))
                    .build()
                    .verify(token)
                    .getSubject();
        } catch (TokenExpiredException e){
            throw new RuntimeException("token不存在或已过期");
        } catch (Exception e){
            throw new RuntimeException("token不存在或已过期");
        }
    }

    /**
     * 判断token是否需要更新
     * @param token
     * @return
     */
    public static boolean tokenIsNeedUpdate(String token) {
        // 获取过期时间
        Date expiresTime = null;
        try {
            expiresTime = JWT.require(Algorithm.HMAC512(jwtConfig.getSecret()))
                          .build()
                          .verify(token)
                          .getExpiresAt();
        } catch (TokenExpiredException e) {
            return true;
        }catch(Exception e){
            throw new RuntimeException("token验证失败");
        }
        // 若剩余时间少于过期时长的一半则更新
        return (expiresTime.getTime() - System.currentTimeMillis()) < (jwtConfig.getExpireTime()*30*1000);
    }

    /**
     * 解密payload
     * @param token
     * @return
     */
    public static String parseJwt(String token){
        return new String(Base64.decodeBase64(JWT.require(Algorithm.HMAC512(jwtConfig.getSecret()))
        .build()
        .verify(token)
        .getPayload()));
    }
}
